package main

import (
	"context"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/go-admin-team/go-admin-core/config/source/file"
	"github.com/go-admin-team/go-admin-core/sdk/api"
	"github.com/go-admin-team/go-admin-core/sdk/pkg"
	"github.com/go-admin-team/go-admin-core/sdk/pkg/captcha"
	"log"
	"net/http"
	"os"
	"os/signal"
	"time"
	"vrcm/src/vrcm/app/admin/router"
	_ "vrcm/src/vrcm/app/admin/router/comment"
	_ "vrcm/src/vrcm/app/admin/router/domian"
	_ "vrcm/src/vrcm/app/admin/router/draw"
	_ "vrcm/src/vrcm/app/admin/router/dynamic"
	_ "vrcm/src/vrcm/app/admin/router/email"
	_ "vrcm/src/vrcm/app/admin/router/im"
	_ "vrcm/src/vrcm/app/admin/router/likes"
	_ "vrcm/src/vrcm/app/admin/router/live"
	_ "vrcm/src/vrcm/app/admin/router/live_schedule"
	_ "vrcm/src/vrcm/app/admin/router/media"
	_ "vrcm/src/vrcm/app/admin/router/monitor"
	_ "vrcm/src/vrcm/app/admin/router/notice"
	_ "vrcm/src/vrcm/app/admin/router/sms"
	_ "vrcm/src/vrcm/app/admin/router/subject"
	_ "vrcm/src/vrcm/app/admin/router/view"
	_ "vrcm/src/vrcm/app/admin/router/wechat"
	"vrcm/src/vrcm/app/job"
	"vrcm/src/vrcm/common/config"
	"vrcm/src/vrcm/common/database"
	"vrcm/src/vrcm/common/global"
	common "vrcm/src/vrcm/common/middleware"
	"vrcm/src/vrcm/common/middleware/handler"
	"vrcm/src/vrcm/common/runtime"
	ext "vrcm/src/vrcm/envconfig"
	"vrcm/src/vrcm/sdk"
)

//go:generate swag init --parseDependency --parseDepth=6

// @title vrcm API
// @version 2.0.0
// @description 基于Gin + Vue + Element UI的前后端分离权限管理系统的接口文档
// @description 添加qq群: 521386980 进入技术交流群 请先star，谢谢！
// @license.name MIT
// @license.url https://github.com/go-admin-team/go-admin/blob/master/LICENSE.md

// @securityDefinitions.apikey Bearer
// @in header
// @name Authorization
var AppRouters = make([]func(), 0)

//var Runtime runtime.Runtime = runtime.NewConfig()

func init() {
	AppRouters = append(AppRouters, router.InitRouter)
}
func main() {
	// 注入配置扩展项
	config.ExtendConfig = &ext.ExtConfig
	//1. 读取配置
	config.Setup(
		file.NewSource(file.WithPath("/usr/local/vs_conf/vrcm.yaml")),
		//file.NewSource(file.WithPath("/usr/local/vrcm/envconfig/dev_config.yaml")),
		//file.NewSource(file.WithPath("envconfig/dev_config.yaml")),
		database.Setup,
		Setup,
	)
	//注册监听函数
	//queue := sdk.Runtime.GetMemoryQueue("")
	//queue.Register(global.LoginLog, models.SaveLoginLog)
	//queue.Register(global.OperateLog, models.SaveOperaLog)
	//queue.Register(global.ApiCheck, models.SaveSysApi)
	//go queue.Run()

	usageStr := `starting api server...`
	log.Println(usageStr)

	if config.ApplicationConfig.Mode == pkg.ModeProd.String() {
		gin.SetMode(gin.ReleaseMode)
	}

	//初始化家在路由
	initRouter()
	for _, f := range AppRouters {
		f()
	}
	srv := &http.Server{
		Addr:    fmt.Sprintf("%s:%d", config.ApplicationConfig.Host, config.ApplicationConfig.Port),
		Handler: sdk.Runtime.GetEngine(),
	}

	job.InitJob()

	//// 通过调度器创建worker，监听来自 JobQueue的任务
	//pool := apis.NewPool(5)
	//pool.Run()

	if len(ext.ExtConfig.ServiceConfig.VsApiServiceUrl) > 0 {
		ext.ExtConfig.ServiceConfig.VrmServiceUrl = ext.ExtConfig.ServiceConfig.VsApiServiceUrl + "/vrm"
		ext.ExtConfig.ServiceConfig.NgvsaServiceUrl = ext.ExtConfig.ServiceConfig.VsApiServiceUrl + "/ngvsa"
		ext.ExtConfig.ServiceConfig.VrcmServiceUrl = ext.ExtConfig.ServiceConfig.VsApiServiceUrl + "/vrcm"
		ext.ExtConfig.ServiceConfig.VrcServiceUrl = ext.ExtConfig.ServiceConfig.VsApiServiceUrl + "/vrc"
		ext.ExtConfig.ServiceConfig.VruServiceUrl = ext.ExtConfig.ServiceConfig.VsApiServiceUrl + "/vru"
		ext.ExtConfig.ServiceConfig.AlertServiceUrl = ext.ExtConfig.ServiceConfig.VsApiServiceUrl + "/doraemon"
		ext.ExtConfig.ServiceConfig.VrpmServiceUrl = ext.ExtConfig.ServiceConfig.VsApiServiceUrl + "/vrpm"
		ext.ExtConfig.ServiceConfig.VdaServiceUrl = ext.ExtConfig.ServiceConfig.VsApiServiceUrl + "/vda"
		ext.ExtConfig.ServiceConfig.VrbmServiceUrl = ext.ExtConfig.ServiceConfig.VsApiServiceUrl + "/vrbm"
		//ext.ExtConfig.ServiceConfig.NexaServiceUrl = ext.ExtConfig.ServiceConfig.VsApiServiceUrl + "/nexa"
	}

	go func() {
		// 服务连接
		if config.SslConfig.Enable {
			if err := srv.ListenAndServeTLS(config.SslConfig.Pem, config.SslConfig.KeyStr); err != nil && err != http.ErrServerClosed {
				log.Fatal("listen: ", err)
			}
		} else {
			if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
				log.Fatal("listen: ", err)
			}
		}
	}()

	fmt.Println(pkg.Red(string(global.LogoContent)))
	tip()
	fmt.Println(pkg.Green("Server run at:"))
	fmt.Printf("-  Local:   http://localhost:%d/ \r\n", config.ApplicationConfig.Port)
	fmt.Printf("-  Network: http://%s:%d/ \r\n", pkg.GetLocaHonst(), config.ApplicationConfig.Port)
	fmt.Println(pkg.Green("Swagger run at:"))
	fmt.Printf("-  Local:   http://localhost:%d/swagger/admin/index.html \r\n", config.ApplicationConfig.Port)
	fmt.Printf("-  Network: http://%s:%d/swagger/admin/index.html \r\n", pkg.GetLocaHonst(), config.ApplicationConfig.Port)
	fmt.Printf("%s Enter Control + C Shutdown Server \r\n", pkg.GetCurrentTimeStr())
	// 等待中断信号以优雅地关闭服务器（设置 5 秒的超时时间）
	quit := make(chan os.Signal)
	signal.Notify(quit, os.Interrupt)
	<-quit

	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	fmt.Printf("%s Shutdown Server ... \r\n", pkg.GetCurrentTimeStr())

	if err := srv.Shutdown(ctx); err != nil {
		log.Fatal("Server Shutdown:", err)
	}
	log.Println("Server exiting")

}

var Router runtime.Router

func tip() {
	usageStr := `欢迎使用 ` + pkg.Green(`vrcm `+global.Version) + ` 可以使用 ` + pkg.Red(`-h`) + ` 查看命令`
	fmt.Printf("%s \n\n", usageStr)
}

func initRouter() {
	var r *gin.Engine
	h := sdk.Runtime.GetEngine()
	if h == nil {
		h = gin.New()
		sdk.Runtime.SetEngine(h)
	}
	switch h.(type) {
	case *gin.Engine:
		r = h.(*gin.Engine)
	default:
		log.Fatal("not support other engine")
		os.Exit(-1)
	}
	if config.SslConfig.Enable {
		r.Use(handler.TlsHandler())
	}
	common.InitMiddleware(r)
	//r.Use(middleware.Metrics())
	//r.Use(common.Sentinel()).
	//r.Use(common.RequestId(pkg.TrafficKey)).
	r.Use(api.SetRequestLogger)

}

// Setup 配置storage组件
func Setup() {
	//4. 设置缓存
	cacheAdapter, err := config.CacheConfig.Setup()
	if err != nil {
		log.Fatalf("cache setup error, %s\n", err.Error())
	}
	sdk.Runtime.SetCacheAdapter(cacheAdapter)
	//5. 设置验证码store
	captcha.SetStore(captcha.NewCacheStore(cacheAdapter, 600))

	//6. 设置队列
	if !config.QueueConfig.Empty() {
		if q := sdk.Runtime.GetQueueAdapter(); q != nil {
			q.Shutdown()
		}
		queueAdapter, err := config.QueueConfig.Setup()
		if err != nil {
			log.Fatalf("queue setup error, %s\n", err.Error())
		}
		sdk.Runtime.SetQueueAdapter(queueAdapter)
		defer func() {
			go queueAdapter.Run()
		}()
	}

	//7. 设置分布式锁
	if !config.LockerConfig.Empty() {
		lockerAdapter, err := config.LockerConfig.Setup()
		if err != nil {
			log.Fatalf("locker setup error, %s\n", err.Error())
		}
		sdk.Runtime.SetLockerAdapter(lockerAdapter)
	}
}
